package com.interviews.forkjoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * forkjoin 实例
 * ForkJoinPool，这个线程池是在 JDK 7 加入的，它的名字 ForkJoin 也描述了它的执行机制，主要用法和之前的线程池是相同的，
 * 也是把任务交给线程池去执行，线程池中也有任务队列来存放任务。但是 ForkJoinPool 线程池和之前的线程池有两点非常大的不同
 * 之处。第一点它非常适合执行可以产生子任务的任务。
 *
 * 之前的线程池所有的线程共用一个队列，但 ForkJoinPool 线程池中每个线程都有自己独立的任务队列
 * ForkJoinPool 非常适合用于递归的场景，例如树的遍历、最优路径搜索等场景
 *
 * @author qian
 * @version 1.0
 * @date 2022/2/28 14:41
 */

class Fibonacci extends RecursiveTask<Integer> {

    /**
     * 举个例子，比如面试中经常考到的菲波那切数列，你一定非常熟悉，
     * 这个数列的特点就是后一项的结果等于前两项的和，第 0 项是 0，
     * 第 1 项是 1，那么第 2 项就是 0+1=1，以此类推。
     */
    int n;

    public Fibonacci(int n) {
        this.n = n;
    }

    @Override
    protected Integer compute() {
        if (n <= 1) {
            return n;
        }
        Fibonacci f1 = new Fibonacci(n - 1);
        f1.fork();
        Fibonacci f2 = new Fibonacci(n - 2);
        f2.fork();
        return f1.join() + f2.join();
    }
}

public class ForkJoinDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        System.out.println("将会打印出斐波那契数列的第 0 到 9 项的值");
        for (int i = 0; i < 10; i++) {
            ForkJoinTask<Integer> task = forkJoinPool.submit(new Fibonacci(i));
            System.out.println(task.get());
        }
    }
}
